package com.cloudfun.campusshare.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.cloudfun.campusshare.common.constant.BusinessConstant;
import com.cloudfun.campusshare.common.constant.Code;
import com.cloudfun.campusshare.common.constant.VerifyType;
import com.cloudfun.campusshare.common.response.BaseResult;
import com.cloudfun.campusshare.common.response.BaseResultFactory;
import com.cloudfun.campusshare.entity.DeviceEntity;
import com.cloudfun.campusshare.entity.UserEntity;
import com.cloudfun.campusshare.repo.DeviceEntityRepo;
import com.cloudfun.campusshare.repo.UserEntityRepo;
import com.cloudfun.campusshare.service.DeviceOpServiceDelegate;
import com.cloudfun.campusshare.service.VerifyCodeService;
import com.cloudfun.campusshare.util.SendMailUtil;
import com.cloudfun.campusshare.util.tencent.TencentSMSUtil;
import com.github.qcloudsms.SmsSingleSenderResult;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author linyangping
 * @date 2019/10/21
 */
@Service
@Slf4j
public class VerifyCodeServiceImpl implements VerifyCodeService {

    @Autowired
    private BusinessConstant businessConstant;

    @Autowired
    private UserEntityRepo userEntityRepo;

    @Autowired
    private DefaultKaptcha defaultKaptcha;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private DeviceEntityRepo deviceEntityRepo;

    @Autowired
    private DeviceOpServiceDelegate deviceOpService;

    // 过期时间
    private static final Integer OVERDUE = 60 * 5;

    // 腾讯验证码模板
    private static final Integer VERIFY_SMS_TEMPLATE = 513530;

    @Override
    @SneakyThrows
    public BaseResult<?> phoneCodeCreate(VerifyType type, String phone) {
        BaseResult<?> baseResult = new BaseResult<>();

        if (businessConstant.DEBUG) {
            baseResult.returnWithoutValue(Code.SUCCESS);
            return baseResult;
        }

        UserEntity userEntity = userEntityRepo.findbyPhone(phone);
        if (VerifyType.REGISTER.equals(type)) {
            // 判断用户是否已经存在
            if (!ObjectUtils.isEmpty(userEntity)) {
                return BaseResultFactory.produceEmptyResult(Code.PHONE_EXIST);
            }
        }
        if (VerifyType.RESET.equals(type)) {
            // 判断用户是否已经存在
            if (ObjectUtils.isEmpty(userEntity)) {
                return BaseResultFactory.produceEmptyResult(Code.PHONE_UNEXIST);
            }
        }

        Date date = new Date();
        String time = String.valueOf(date.getTime());
        String verifyCode = time.substring(time.length() - 6);
        // 记录验证码
        stringRedisTemplate.opsForValue().set(type + phone, verifyCode, OVERDUE, TimeUnit.SECONDS);
        // 发送验证码
        String params[] = new String[2];
        params[0] = verifyCode;
        params[1] = "5";
        SmsSingleSenderResult smsSingleSenderResult = TencentSMSUtil.sendSMSWithParams(phone, VERIFY_SMS_TEMPLATE, params);


        if (smsSingleSenderResult.result != Code.SUCCESS.getCode()) {
            baseResult.setCode(smsSingleSenderResult.result);
            baseResult.setMessage(smsSingleSenderResult.errMsg);
            return baseResult;
        }

        baseResult.returnWithoutValue(Code.SUCCESS);
        return baseResult;

    }

    @Override
    public BaseResult<String> getPhoneCode(VerifyType type, String phone) {
        return BaseResultFactory.produceResult(Code.SUCCESS, stringRedisTemplate.opsForValue().get(type + phone));
    }

    @Override
    @SneakyThrows
    public BaseResult phoneCodeCreate(VerifyType type, String phone, String verifyCode) {
        BaseResult baseResult = new BaseResult();

        if (businessConstant.DEBUG) {
            baseResult.returnWithoutValue(Code.SUCCESS);
            return baseResult;
        }
        // 记录验证码
        stringRedisTemplate.opsForValue().set(type + phone, verifyCode, OVERDUE, TimeUnit.SECONDS);
        // 发送验证码
        String[] params = new String[2];
        params[0] = verifyCode;
        params[1] = "5";
        //SmsSingleSenderResult smsSingleSenderResult = TencentSMSUtil.sendSMS(phone, typeNum, verifyCode);
        SmsSingleSenderResult smsSingleSenderResult = TencentSMSUtil.sendSMSWithParams(phone, VERIFY_SMS_TEMPLATE, params);

        if (smsSingleSenderResult.result != Code.SUCCESS.getCode()) {
            baseResult.setCode(smsSingleSenderResult.result);
            baseResult.setMessage(smsSingleSenderResult.errMsg);
            return baseResult;
        }

        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);

    }

    @Override
    public BaseResult<?> verifyVerifyCode(VerifyType type, String destination, String inputCode) {

        if (businessConstant.DEBUG) {
            return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
        }

        String random = stringRedisTemplate.opsForValue().get(type + destination);

        if (StringUtils.isEmpty(random)) {
            log.info("无验证码");
            return BaseResultFactory.produceEmptyResult(Code.VERIFY_CODE_ERROR);
        }

        if (!StringUtils.equalsIgnoreCase(random, inputCode)) {
            log.error("原验证码:{}, 输入验证码:{}", random, inputCode);
            return BaseResultFactory.produceEmptyResult(Code.VERIFY_CODE_ERROR);
        }
        // 清除验证码
        stringRedisTemplate.delete(type + destination);

        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);

    }

    @SneakyThrows
    public void getCaptcha(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, VerifyType verifyType) {
        httpServletResponse.setHeader("Cache-Control", "no-store");
        httpServletResponse.setHeader("Pragma", "no-cache");
        httpServletResponse.setDateHeader("Expires", 0);
        httpServletResponse.setContentType(MediaType.IMAGE_JPEG_VALUE);
        String sessionId = httpServletRequest.getSession().getId();
        try (ServletOutputStream outputStream = httpServletResponse.getOutputStream();) {
            // 生产验证码字符串并保存到session中
            String verifyCode = defaultKaptcha.createText();
            // 生成图形验证码
            BufferedImage challenge = defaultKaptcha.createImage(verifyCode);
            ImageIO.write(challenge, "jpg", outputStream);
            // 记录验证码
            stringRedisTemplate.opsForValue().set(verifyType + sessionId, verifyCode, OVERDUE, TimeUnit.SECONDS);
        }
    }

    @Override
    public boolean verifyCaptcha(HttpServletRequest httpServletRequest, VerifyType verifyType, String captcha) {
        String sessionId = httpServletRequest.getSession().getId();
        String expectedCaptcha = stringRedisTemplate.opsForValue().get(verifyType + sessionId);
        if (StringUtils.isEmpty(expectedCaptcha)) {
            return false;
        }
        boolean match = StringUtils.equalsIgnoreCase(expectedCaptcha, captcha);
        if (match) {
            stringRedisTemplate.delete(verifyType + sessionId);
        }
        return match;
    }

    @Override
    @SneakyThrows
    public BaseResult emailCodeCreate(VerifyType verifyType, String email, HttpServletResponse response, HttpSession session) {
        if (businessConstant.DEBUG) {
            return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
        }
        Date date = new Date();
        String time = String.valueOf(date.getTime());
        String verifyCode = time.substring(time.length() - 6);
        // 记录验证码
        stringRedisTemplate.opsForValue().set(verifyType.name() + email, verifyCode, OVERDUE, TimeUnit.SECONDS);
        // 发送验证码
        boolean result = SendMailUtil.sendEmail(email, "绑定邮箱", getEmailWithCode(verifyCode));
        if (result) {
            return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
        } else {
            return BaseResultFactory.produceEmptyResult(Code.EMAIL_ERROR);
        }
    }

    @Override
    public BaseResult<?> deviceCodeCreate(String deviceId) {
        Optional<DeviceEntity> deviceOpt = deviceEntityRepo.findById(deviceId);
        if (!deviceOpt.isPresent()) {
            return BaseResultFactory.produceEmptyResult(Code.NODATA);
        }
        DeviceEntity deviceEntity = deviceOpt.get();
        String time = String.valueOf(new Date().getTime());
        String verifyCode = time.substring(time.length() - 4);
        // 记录验证码
        stringRedisTemplate.opsForValue().set(VerifyType.DEVICE + deviceId, verifyCode, OVERDUE, TimeUnit.SECONDS);
        // 发送验证码
        return deviceOpService.deviceVerifyCode(deviceEntity.getImei(), verifyCode);
    }

    private String getEmailWithCode(String content) {
        String result = "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html xmlns='http://www.w3.org/1999/xhtml'><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /><title></title><meta name='viewport' content='width=device-width, initial-scale=1.0'/></head><body style='margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px; padding-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;'><div style='width: 1040px; background-color: #F5F6F7; padding: 52px 0;'><div style='width: 608px;margin: 0 auto;background-color: #fff;'><div style='background-color: #1D2437; height: 52px; text-align: center;line-height: 52px;'><img src='http://zeus.nos-eastchina1.126.net/4a62469d2c11045368773349064f7bfc455e83a8d11dc67e9262cfb996c6ffc5.svg' alt='' height='30px' style='vertical-align: middle; padding-bottom: 8px;'><span style='width: 2px;background-color: #ffffff; opacity: 0.45;height: 14px;display: inline-block;margin: 0 7px;'></span><span style='font-size:16px;              font-weight:500;              color:rgba(255,255,255,1);              line-height:52px;'>安全可信的一站式存证服务平台</span></div><div style='padding: 40px 34px 32px 48px;'><p style='font-size:14px;              font-weight:500;              color:rgba(102,103,105,1);              line-height:20px;margin-bottom: 4px;margin-top: 0;'>尊敬的用户：</p ><p style='font-size:14px;              font-weight:500;              color:rgba(102,103,105,1);              line-height:20px;margin-bottom: 4px;margin-top: 0;'>您好，感谢您使用飞洛印平台！</p ><p style='font-size:14px;              font-weight:500;              color:rgba(102,103,105,1);              line-height:20px;margin-bottom: 4px;margin-top: 0;'>您的验证码为: </p ><p style='font-size:24px;              font-weight:500;              color: #2D7FEB;             line-height:20px;margin-bottom: 20px;margin-top: 20px;'>" + content + "</p ><br><p style='font-size:14px;              font-weight:500;              color:rgba(102,103,105,1);              line-height:20px;margin-bottom: 4px;margin-top: 0;'>本邮件为系统发送，无需回复。</p ><p style='font-size:14px;              font-weight:500;              color:rgba(102,103,105,1);              line-height:20px;margin-bottom: 0px;margin-top: 20px;padding-right: 14px;text-align: right;'>飞洛印服务团队</p ></div></div></div></table></body></html>";
        return result;
    }

}
